ti: k3: common: Add support for runtime detection of GICR base address
authorAndrew F. Davis <[email protected]>
Tue, 22 Jan 2019 18:39:31 +0000 (12:39 -0600)
committerAndrew F. Davis <[email protected]>
Tue, 22 Jan 2019 19:11:09 +0000 (13:11 -0600)
Valid addresses for GICR base are always a set calculable distance from
the GICD and is based on the number of cores a given instance of GICv3 IP
can support. The formula for the number of address bits is given by the
ARM GIC-500 TRM section 3.2 as 2^(18+log2(cores)) with the MSB set to
one for GICR instances. Holes in the GIC address space are also
guaranteed to safely return 0 on reads. This allows us to support runtime
detection of the GICR base address by starting from GIC base address plus
BIT(18) and walking until the GICR ID register (IIDR) is detected. We
stop searching after BIT(20) to prevent searching out into space if
something goes wrong. This can be extended out if we ever have a device
with 16 or more cores.

Signed-off-by: Andrew F. Davis <[email protected]>
include/drivers/arm/gicv3.h
plat/ti/k3/common/k3_bl31_setup.c
plat/ti/k3/common/k3_gicv3.c
plat/ti/k3/include/k3_gicv3.h
plat/ti/k3/include/platform_def.h

index 2382697748b585e3e85972efcc0c36aaedceb04f..72221acb0fc96d9dd51dbd6922abf91498fdc249 100644 (file)
@@ -84,6 +84,7 @@
 #define GICR_PCPUBASE_SHIFT    0x11
 #define GICR_SGIBASE_OFFSET    U(65536)        /* 64 KB */
 #define GICR_CTLR              U(0x0)
+#define GICR_IIDR              U(0x04)
 #define GICR_TYPER             U(0x08)
 #define GICR_WAKER             U(0x14)
 #define GICR_PROPBASER         U(0x70)
index 3fa11b2318ec00c73a6707ced936aab8b0313942..78fb696b2200c51db665015a2f45833a03a118f4 100644 (file)
@@ -23,8 +23,7 @@
 const mmap_region_t plat_k3_mmap[] = {
        MAP_REGION_FLAT(SHARED_RAM_BASE, SHARED_RAM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
-       MAP_REGION_FLAT(K3_GICD_BASE, K3_GICD_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
-       MAP_REGION_FLAT(K3_GICR_BASE, K3_GICR_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+       MAP_REGION_FLAT(K3_GIC_BASE, K3_GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
        MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
@@ -116,7 +115,7 @@ void bl31_plat_arch_setup(void)
 
 void bl31_platform_setup(void)
 {
-       k3_gic_driver_init(K3_GICD_BASE, K3_GICR_BASE);
+       k3_gic_driver_init(K3_GIC_BASE);
        k3_gic_init();
 
        ti_sci_init();
index b7c7880141ffe9fec1583cfcaf575164f64b55c8..1932eaae571c2fe05a3f748d64b35b8911339411 100644 (file)
@@ -6,10 +6,12 @@
 
 #include <platform_def.h>
 
+#include <assert.h>
 #include <common/bl_common.h>
 #include <common/interrupt_props.h>
 #include <drivers/arm/gicv3.h>
 #include <lib/utils.h>
+#include <lib/mmio.h>
 #include <plat/common/platform.h>
 
 #include <k3_gicv3.h>
@@ -35,8 +37,25 @@ gicv3_driver_data_t k3_gic_data = {
        .mpidr_to_core_pos = k3_mpidr_to_core_pos,
 };
 
-void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base)
+void k3_gic_driver_init(uintptr_t gic_base)
 {
+       /* GIC Distributor is always at the base of the IP */
+       uintptr_t gicd_base = gic_base;
+       /* GIC Redistributor base is run-time detected */
+       uintptr_t gicr_base = 0;
+
+       for (unsigned int gicr_shift = 18; gicr_shift < 21; gicr_shift++) {
+               uintptr_t gicr_check = gic_base + BIT(gicr_shift);
+               uint32_t iidr = mmio_read_32(gicr_check + GICR_IIDR);
+               if (iidr != 0) {
+                       /* Found the GICR base */
+                       gicr_base = gicr_check;
+                       break;
+               }
+       }
+       /* Assert if we have not found the GICR base */
+       assert(gicr_base != 0);
+
        /*
         * The GICv3 driver is initialized in EL3 and does not need
         * to be initialized again in SEL1. This is because the S-EL1
index 52f34ff1f693682af8d345a43cf69120c6fc6008..2329a16e573f340941dc7f074eb58328455f4412 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <stdint.h>
 
-void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base);
+void k3_gic_driver_init(uintptr_t gic_base);
 void k3_gic_init(void);
 void k3_gic_cpuif_enable(void);
 void k3_gic_cpuif_disable(void);
index 9447f04df3eb28b6c741895ee92b23dd6a866b17..f1511c136dcd689ee1703baca8847d8d079d087e 100644 (file)
        INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
                        GIC_INTR_CFG_EDGE)
 
-#define K3_GICD_BASE  0x01800000
-#define K3_GICD_SIZE  0x10000
-#define K3_GICR_BASE  0x01880000
-#define K3_GICR_SIZE  0x100000
+#define K3_GIC_BASE    0x01800000
+#define K3_GIC_SIZE    0x200000
 
 #define SEC_PROXY_DATA_BASE    0x32C00000
 #define SEC_PROXY_DATA_SIZE    0x80000